package com.baidu.iit.pxp.handler;

import com.baidu.iit.pxp.constants.ImplementationTypeConstants;
import com.baidu.iit.pxp.entity.ProcessDefinitionEntity;
import com.baidu.iit.pxp.event.ActivityEventType;
import com.baidu.iit.pxp.model.*;
import com.baidu.iit.pxp.model.Process;
import com.baidu.iit.pxp.parser.BpmnParse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: huangweili
 * Date: 14-4-30
 * Time: 上午10:22
 */
public class ProcessParseHandler extends AbstractBpmnParseHandler<Process> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ProcessParseHandler.class);

    public static final String PROPERTYNAME_DOCUMENTATION = "documentation";

    public Class<? extends BaseElement> getHandledType() {
        return Process.class;
    }

    protected void executeParse(BpmnParse bpmnParse, Process process) {
        bpmnParse.getProcessDefinitions().add(transformProcess(bpmnParse, process));
    }

    protected ProcessDefinitionEntity transformProcess(BpmnParse bpmnParse, Process process) {
        ProcessDefinitionEntity currentProcessDefinition = new ProcessDefinitionEntity();
        bpmnParse.setCurrentProcessDefinition(currentProcessDefinition);

        currentProcessDefinition.setKey(process.getId());
        currentProcessDefinition.setName(process.getName());

        currentProcessDefinition.setCategory(bpmnParse.getBpmnModel().getTargetNamespace());
        currentProcessDefinition.setDescription(process.getDocumentation());

        currentProcessDefinition.setProperty(PROPERTYNAME_DOCUMENTATION, process.getDocumentation()); // Kept for backwards compatibility. See ACT-1020
        currentProcessDefinition.setTaskDefinitions(new HashMap<String, TaskDefinition>());
        createExecutionListenersOnScope(bpmnParse, process.getExecutionListeners(), currentProcessDefinition);
        createEventListeners(bpmnParse, process.getEventListeners(), currentProcessDefinition);
        bpmnParse.setCurrentScope(currentProcessDefinition);

        bpmnParse.processFlowElements(process.getFlowElements());

        Map<String, Object> variables = processDataObjects(bpmnParse, process.getDataObjects(), currentProcessDefinition);
        if (null != currentProcessDefinition.getVariables()) {
            currentProcessDefinition.getVariables().putAll(variables);
        } else {
            currentProcessDefinition.setVariables(variables);
        }

        bpmnParse.removeCurrentScope();

        return currentProcessDefinition;
    }

    protected void createEventListeners(BpmnParse bpmnParse, List<EventListener> eventListeners,
                                        ProcessDefinitionEntity currentProcessDefinition) {

        if (eventListeners != null && !eventListeners.isEmpty()) {
            for (EventListener eventListener : eventListeners) {
                ActivityEventType[] types = ActivityEventType.getTypesFromString(eventListener.getEvents());

                if (ImplementationTypeConstants.IMPLEMENTATION_TYPE_CLASS.equals(eventListener.getImplementationType())) {
                    currentProcessDefinition.getEventSupport().addEventListener(
                            bpmnParse.getListenerFactory().createClassDelegateEventListener(eventListener), types);
                } else if (ImplementationTypeConstants.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(eventListener.getImplementationType())) {
                    currentProcessDefinition.getEventSupport().addEventListener(
                            bpmnParse.getListenerFactory().createDelegateExpressionEventListener(eventListener), types);
                } else {
                    LOGGER.warn("Unsupported implementation type for EventLIstener: " + eventListener.getImplementationType()
                            + " for element " + bpmnParse.getCurrentFlowElement().getId());
                }
            }
        }

    }

}
